home *** CD-ROM | disk | FTP | other *** search
/ MacTech 1 to 12 / MacTech-vol-1-12.toast / Source / SpriteWorld 2.0 ƒ / SpriteWorld Examples / SimpleBreakOut / SimpleBreakOut.c < prev    next >
Encoding:
C/C++ Source or Header  |  1996-10-05  |  15.8 KB  |  591 lines  |  [TEXT/KAHL]

  1. ///--------------------------------------------------------------------------------------
  2. // SimpleBreakOut.c
  3. //
  4. // Portions are Copyright © 1993 Tony Myles, All rights reserved worldwide.
  5. //
  6. // Description: This is a very basic breakout type game that demonstrates
  7. // SpriteWorld's efficient handling of inactive sprites.
  8. ///--------------------------------------------------------------------------------------
  9.  
  10.  
  11. #include <SWIncludes.h>            // Automatically include all SpriteWorld.h files
  12. #include <SWGameUtils.h>
  13.  
  14. #include "SWApplication.h"
  15. #include "SimpleBreakOut.h"
  16.  
  17.  
  18.  
  19. #define kMaxFPS                    0                // Set to 0 for maximum speed
  20. #define kSyncToVBL                true            // Sync animation to VBL?
  21.  
  22.  
  23. enum
  24. {
  25.     kBallHorizDelta = 5,
  26.     kBallVertDelta = 5,
  27.     kNumberOfBrickColumns = 10,
  28.     kNumberOfBrickRows = 5,
  29.     kTotalNumberOfBricks = (kNumberOfBrickColumns * kNumberOfBrickRows),
  30.     kBrickCIconID = 129,
  31.     kBreakBallCIconID = 130,
  32.     kPaddleCIconID = 131
  33. };
  34.  
  35.  
  36.  
  37. Point        oldPoint, newPoint;            // Mouse variables used for moving paddle
  38. short        gBrickNum;
  39.  
  40.  
  41. ///--------------------------------------------------------------------------------------
  42. // main
  43. ///--------------------------------------------------------------------------------------
  44.  
  45. void main(void)
  46. {
  47.     WindowPtr    myWindowP = NULL;
  48.     Rect        windRect;
  49.     
  50.     
  51.     Initialize(kNumberOfMoreMastersCalls);
  52.     
  53.     if (!SWHasSystem7())
  54.         CantRunOnThisMachine();
  55.  
  56.  
  57.         // Create and set up the window
  58.     myWindowP = GetNewCWindow(kWindowResID, NULL, (WindowPtr)-1L);
  59.  
  60.     if (myWindowP != NULL)
  61.     {
  62.             // Center window in screen
  63.         windRect = myWindowP->portRect;
  64.         CenterRect(&windRect, &qd.screenBits.bounds);
  65.         MoveWindow(myWindowP, windRect.left, windRect.top, false);
  66.         
  67.         ShowWindow(myWindowP);
  68.         SetPort(myWindowP);
  69.     }
  70.     else
  71.         CantFindResource();
  72.     
  73.  
  74.     PerformSimpleAnimation((CWindowPtr)myWindowP);
  75. }
  76.  
  77.  
  78. ///--------------------------------------------------------------------------------------
  79. // PerformSimpleAnimation
  80. ///--------------------------------------------------------------------------------------
  81.  
  82. void PerformSimpleAnimation(CWindowPtr srcWindowP)
  83. {
  84.     OSErr                    err;
  85.     PixPatHandle        pixPatH;
  86.     
  87.     SpriteWorldPtr        spriteWorldP;
  88.     SpriteLayerPtr        brickLayerP;
  89.     SpriteLayerPtr        ballLayerP;
  90.     SpriteLayerPtr        paddleLayerP;
  91.     SpritePtr            brickSpriteArray[kTotalNumberOfBricks];
  92.     SpritePtr            ballSpriteP;
  93.     SpritePtr            paddleSpriteP;
  94.     
  95.     short        horizOffset, vertOffset, brickHoriz, brickVert, col, row, n;
  96.     Rect        moveBoundsRect;
  97.  
  98.  
  99.     SetPort((GrafPtr)srcWindowP);
  100.     SetCursor(*GetCursor(watchCursor));
  101.  
  102.  
  103.     //
  104.     // STEP #1: initialize the sprite world package
  105.     //
  106.  
  107.     err = SWEnterSpriteWorld();
  108.     FatalError(err);
  109.  
  110.  
  111.     //
  112.     // STEP #2: create the various pieces that we need
  113.     //
  114.  
  115.         // create the sprite world
  116.     err = SWCreateSpriteWorldFromWindow(&spriteWorldP, srcWindowP, NULL, NULL);
  117.     FatalError(err);
  118.  
  119.         // create the brick layer
  120.     err = SWCreateSpriteLayer(&brickLayerP);
  121.     FatalError(err);
  122.  
  123.         // create the ball layer
  124.     err = SWCreateSpriteLayer(&ballLayerP);
  125.     FatalError(err);
  126.  
  127.         // create the paddle layer
  128.     err = SWCreateSpriteLayer(&paddleLayerP);
  129.     FatalError(err);
  130.  
  131.         // Create the first brick sprite
  132.     err = SWCreateSpriteFromCicnResource(spriteWorldP, &(brickSpriteArray[0]), NULL, 
  133.                 kBrickCIconID, 1, kNoMask);
  134.  
  135.         // Clone the other brick sprites off the first one
  136.     for (gBrickNum = 1; gBrickNum < kTotalNumberOfBricks; gBrickNum++)
  137.     {
  138.         err = SWCloneSprite(brickSpriteArray[0], &brickSpriteArray[gBrickNum], NULL);
  139.         FatalError(err);
  140.     }
  141.  
  142.         // create ball sprite
  143.     err = SWCreateSpriteFromCicnResource(spriteWorldP, &ballSpriteP, NULL, 
  144.                 kBreakBallCIconID, 1, kFatMask);
  145.     FatalError(err);
  146.  
  147.         // create paddle sprite
  148.     err = SWCreateSpriteFromCicnResource(spriteWorldP, &paddleSpriteP, NULL, 
  149.                 kPaddleCIconID, 1, kFatMask);
  150.     FatalError(err);
  151.  
  152.  
  153.  
  154.     //
  155.     // STEP #3: put the pieces together (must be done BEFORE the sprite world is locked!)
  156.     //
  157.  
  158.     for (gBrickNum = 0; gBrickNum < kTotalNumberOfBricks; gBrickNum++)
  159.     {
  160.             // add the brick sprite to the brick layer
  161.         SWAddSprite(brickLayerP, brickSpriteArray[gBrickNum]);
  162.     }
  163.  
  164.         // add the ball sprite to the ball layer
  165.     SWAddSprite(ballLayerP, ballSpriteP);
  166.  
  167.         // add the paddle sprite to the paddle layer
  168.     SWAddSprite(paddleLayerP, paddleSpriteP);
  169.  
  170.         // add the layers to the world
  171.     SWAddSpriteLayer(spriteWorldP, brickLayerP);
  172.     SWAddSpriteLayer(spriteWorldP, ballLayerP);
  173.     SWAddSpriteLayer(spriteWorldP, paddleLayerP);
  174.     
  175.  
  176.  
  177.     //
  178.     // STEP #4: set things up for the animation
  179.     // (can be done before or after locking the SpriteWorld)
  180.     //
  181.  
  182.         // calculate the movement boundary rectangle
  183.     moveBoundsRect = srcWindowP->portRect;
  184.  
  185.     horizOffset = (brickSpriteArray[0]->curFrameP->frameRect.right - brickSpriteArray[0]->curFrameP->frameRect.left) + 2;
  186.     vertOffset = (brickSpriteArray[0]->curFrameP->frameRect.bottom - brickSpriteArray[0]->curFrameP->frameRect.top) + 2;
  187.     brickHoriz = 2;
  188.     brickVert = (vertOffset * 2);
  189.     gBrickNum = 0;
  190.  
  191.         // set up the bricks
  192.     for (col = 0; col < kNumberOfBrickColumns; col++)
  193.     {
  194.         brickVert = (vertOffset * 2);
  195.  
  196.         for (row = 0; row < kNumberOfBrickRows; row++)
  197.         {
  198.                 // set the sprite’s initial location
  199.             SWSetSpriteLocation(brickSpriteArray[gBrickNum], brickHoriz, brickVert);
  200.             SWSetSpriteMoveTime(brickSpriteArray[gBrickNum], -1);
  201.  
  202.             gBrickNum++;
  203.             brickVert += vertOffset;
  204.         }
  205.     
  206.         brickHoriz += horizOffset;
  207.     }
  208.  
  209.         // set the ball’s movement characteristics
  210.     SWSetSpriteLocation(ballSpriteP, - 100, 50);
  211.     SWSetSpriteMoveBounds(ballSpriteP, &moveBoundsRect);
  212.     SWSetSpriteMoveDelta(ballSpriteP, kBallHorizDelta, kBallVertDelta);
  213.     SWSetSpriteMoveProc(ballSpriteP, BallMoveProc);
  214.     SWSetSpriteCollideProc(ballSpriteP, BallCollideProc);
  215.  
  216.         // set the paddle’s movement characteristics
  217.     SWSetSpriteMoveBounds(paddleSpriteP, &moveBoundsRect);
  218.     SetUpPaddle(paddleSpriteP);
  219.     SWSetSpriteMoveProc(paddleSpriteP, PaddleMoveProc);
  220.     SWSetSpriteCollideProc(paddleSpriteP, PaddleCollideProc);
  221.     
  222.     
  223.     //
  224.     // Set the DrawProcs to BlitPixie
  225.     //
  226.  
  227.         // Set the sprite drawProcs
  228.     if (spriteWorldP->pixelDepth == 8)        // 256 colors
  229.     {
  230.         SWSetSpriteDrawProc(ballSpriteP, BlitPixie8BitMaskDrawProc);
  231.         SWSetSpriteDrawProc(paddleSpriteP, BlitPixie8BitRectDrawProc);
  232.     }
  233.     else                                    // Not 256 colors
  234.     {
  235.         SWSetSpriteDrawProc(ballSpriteP, BlitPixieAllBitMaskDrawProc);
  236.         SWSetSpriteDrawProc(paddleSpriteP, BlitPixieAllBitRectDrawProc);
  237.     }
  238.     
  239.         // Set the screen drawProcs
  240.     if (spriteWorldP->pixelDepth == 8)        // 256 colors
  241.     {
  242.         SWSetSpriteWorldScreenDrawProc(spriteWorldP, BlitPixie8BitRectDrawProc);
  243.         SWSetSpriteWorldOffscreenDrawProc(spriteWorldP, BlitPixie8BitRectDrawProc);
  244.     }
  245.     else                                    // Not 256 colors
  246.     {
  247.         SWSetSpriteWorldScreenDrawProc(spriteWorldP, BlitPixieAllBitRectDrawProc);
  248.         SWSetSpriteWorldOffscreenDrawProc(spriteWorldP, BlitPixieAllBitRectDrawProc);
  249.     }
  250.  
  251.  
  252.  
  253.     //
  254.     // STEP #5: lock the sprite world        !!! VERY IMPORTANT !!!
  255.     //
  256.  
  257.     SWLockSpriteWorld(spriteWorldP);
  258.     
  259.  
  260.     HideCursor();
  261.     
  262.     
  263.     //
  264.     // SETP #6: Draw a nice background. Must be done *after* locking the SpriteWorld!
  265.     //
  266.  
  267.     SWSetPortToBackground(spriteWorldP);
  268.     
  269.     if (spriteWorldP->pixelDepth == 1)
  270.         pixPatH = GetPixPat(129);        // B&W dithered background
  271.     else
  272.         pixPatH = GetPixPat(128);        // Color
  273.     
  274.     if (pixPatH != NULL)
  275.     {
  276.         FillCRect(&moveBoundsRect, pixPatH);
  277.         DisposePixPat(pixPatH);
  278.     }
  279.  
  280.  
  281.     SWSetPortToWindow(spriteWorldP);
  282.  
  283.  
  284.     //
  285.     // STEP #7: update the SpriteWorld and run the animation
  286.     //
  287.  
  288.  
  289.     SetCursor(&qd.arrow);
  290.     SWUpdateSpriteWorld(spriteWorldP, true);
  291.     SWSetSpriteWorldMaxFPS( spriteWorldP, kMaxFPS );
  292.     SWSyncSpriteWorldToVBL(spriteWorldP, kSyncToVBL);
  293.     
  294.     
  295.     while (!Button())
  296.     {
  297.         SWProcessSpriteWorld(spriteWorldP);
  298.  
  299.             // did we lose the last ball?
  300.         if (ballSpriteP->userData == 4)
  301.         {
  302.             SysBeep(1);
  303.             break;
  304.         }
  305.         else if (gBrickNum == 0)
  306.         {
  307.             for (n=0; n<3; n++)
  308.                 SysBeep(1);
  309.             break;
  310.         }
  311.  
  312.             // see if the ball has hit the paddle
  313.         SWCollideSpriteLayer(spriteWorldP, paddleLayerP, ballLayerP);
  314.  
  315.             // see if the ball has hit the bricks
  316.         SWCollideSpriteLayer(spriteWorldP, ballLayerP, brickLayerP);
  317.  
  318.         SWAnimateSpriteWorld(spriteWorldP);
  319.     }
  320.  
  321.  
  322.     //
  323.     // STEP #8: Clean up
  324.     //
  325.  
  326.     SWUnlockSpriteWorld(spriteWorldP);
  327.     SWDisposeSpriteWorld(spriteWorldP);
  328.     SWExitSpriteWorld();
  329.     
  330.     FlushEvents(everyEvent, 0);
  331.     ShowCursor();
  332. }
  333.  
  334.  
  335. ///--------------------------------------------------------------------------------------
  336. // BallCollideProc
  337. ///--------------------------------------------------------------------------------------
  338.  
  339. void BallCollideProc(SpritePtr ballSpriteP, SpritePtr brickSpriteP, Rect* sectRect)
  340. {
  341.     short        offset;
  342.     short        vertMoveDelta = ballSpriteP->vertMoveDelta;
  343.     short        horizMoveDelta = ballSpriteP->horizMoveDelta;
  344.  
  345.  
  346.     if (vertMoveDelta < 0)
  347.         vertMoveDelta = -vertMoveDelta;
  348.     
  349.     if (horizMoveDelta < 0)
  350.         horizMoveDelta = -horizMoveDelta;
  351.     
  352.     if (brickSpriteP->isVisible)
  353.     {
  354.         SWSetSpriteVisible(brickSpriteP, false);
  355.         gBrickNum--;
  356.  
  357.  
  358.         
  359.         if (vertMoveDelta < sectRect->bottom - sectRect->top)
  360.         {
  361.                 // Hit left or right side of brick
  362.             
  363.                 // Reverse direction
  364.             ballSpriteP->horizMoveDelta = -ballSpriteP->horizMoveDelta;
  365.             
  366.                 // "Bounce" ball off bricks
  367.             offset = (sectRect->right - sectRect->left) * 2;
  368.             if (ballSpriteP->horizMoveDelta < 0)
  369.                 offset = -offset;
  370.             
  371.             SWOffsetSprite(ballSpriteP, offset, 0);
  372.         }
  373.         else if (horizMoveDelta < sectRect->right - sectRect->left)
  374.         {
  375.                 // Hit top or bottom of brick
  376.             
  377.                 // Reverse direction
  378.             ballSpriteP->vertMoveDelta = -ballSpriteP->vertMoveDelta;
  379.             
  380.                 // "Bounce" ball off bricks
  381.             offset = (sectRect->bottom - sectRect->top) * 2;
  382.             if (ballSpriteP->vertMoveDelta < 0)
  383.                 offset = -offset;
  384.             
  385.             SWOffsetSprite(ballSpriteP, 0, offset);
  386.         }
  387.         else
  388.         {
  389.                 // Hit corner of brick
  390.                 
  391.             if ((sectRect->right - sectRect->left) > (sectRect->bottom - sectRect->top) )
  392.             {
  393.                     // Hit left or right side of brick
  394.                 
  395.                     // Reverse direction
  396.                 ballSpriteP->horizMoveDelta = -ballSpriteP->horizMoveDelta;
  397.                 
  398.                     // "Bounce" ball off bricks
  399.                 offset = (sectRect->right - sectRect->left) * 2;
  400.                 if (ballSpriteP->horizMoveDelta < 0)
  401.                     offset = -offset;
  402.                 
  403.                 SWOffsetSprite(ballSpriteP, offset, 0);
  404.             }
  405.             else
  406.             {
  407.                     // Hit top or bottom of brick
  408.                 
  409.                     // Reverse direction
  410.                 ballSpriteP->vertMoveDelta = -ballSpriteP->vertMoveDelta;
  411.                 
  412.                     // "Bounce" ball off bricks
  413.                 offset = (sectRect->bottom - sectRect->top) * 2;
  414.                 if (ballSpriteP->vertMoveDelta < 0)
  415.                     offset = -offset;
  416.                 
  417.                 SWOffsetSprite(ballSpriteP, 0, offset);
  418.             }
  419.         }
  420.     }
  421. }
  422.  
  423.  
  424. ///--------------------------------------------------------------------------------------
  425. // PaddleCollideProc
  426. ///--------------------------------------------------------------------------------------
  427.  
  428. void PaddleCollideProc(SpritePtr paddleSpriteP, SpritePtr ballSpriteP, Rect* sectRect)
  429. {
  430.     short    paddleMid = (paddleSpriteP->destFrameRect.right - 
  431.                             paddleSpriteP->destFrameRect.left)/2;
  432.     short    ballMid = (ballSpriteP->destFrameRect.right - 
  433.                             ballSpriteP->destFrameRect.left)/2;
  434.             
  435.     if ( (ballSpriteP->destFrameRect.bottom - ballSpriteP->vertMoveDelta) 
  436.             > paddleSpriteP->destFrameRect.bottom )
  437.         return;                            // Return if ball did not hit above bottom of paddle
  438.     
  439.     
  440.         // Set ball direction according to position hit on paddle
  441.     if (ballSpriteP->destFrameRect.left + ballMid >
  442.          paddleSpriteP->destFrameRect.left + paddleMid)
  443.     {
  444.         ballSpriteP->horizMoveDelta = ( (ballSpriteP->destFrameRect.left + ballMid) - 
  445.                 (paddleSpriteP->destFrameRect.left + paddleMid) )/4;
  446.                 
  447.         if (ballSpriteP->horizMoveDelta > 0)
  448.             ballSpriteP->vertMoveDelta = kBallVertDelta - ballSpriteP->horizMoveDelta/2;
  449.         else
  450.             ballSpriteP->vertMoveDelta = kBallVertDelta + ballSpriteP->horizMoveDelta/2;
  451.         
  452.         if (ballSpriteP->horizMoveDelta == 0)
  453.             ballSpriteP->horizMoveDelta++;
  454.     }
  455.     else
  456.     {
  457.         ballSpriteP->horizMoveDelta = ( (ballSpriteP->destFrameRect.left + ballMid) - 
  458.                 (paddleSpriteP->destFrameRect.left + paddleMid) )/4;
  459.                 
  460.         if (ballSpriteP->horizMoveDelta > 0)
  461.             ballSpriteP->vertMoveDelta = kBallVertDelta - ballSpriteP->horizMoveDelta/2;
  462.         else
  463.             ballSpriteP->vertMoveDelta = kBallVertDelta + ballSpriteP->horizMoveDelta/2;
  464.         
  465.         if (ballSpriteP->horizMoveDelta == 0)
  466.             ballSpriteP->horizMoveDelta--;
  467.     }
  468.  
  469.     
  470.         // If ball was moving down, turn it around
  471.     if (ballSpriteP->vertMoveDelta > 0)
  472.         ballSpriteP->vertMoveDelta = -ballSpriteP->vertMoveDelta;
  473.     
  474.     if ( (ballSpriteP->destFrameRect.bottom - ballSpriteP->vertMoveDelta) 
  475.             > paddleSpriteP->destFrameRect.top )
  476.     {
  477.         SWOffsetSprite(ballSpriteP, 0, sectRect->top - sectRect->bottom);
  478.     }
  479.     
  480. }
  481.  
  482.  
  483. ///--------------------------------------------------------------------------------------
  484. // SetUpPaddle
  485. ///--------------------------------------------------------------------------------------
  486.  
  487. void SetUpPaddle(SpritePtr paddleSpriteP)
  488. {
  489.     short    middle = (paddleSpriteP->moveBoundsRect.right - 
  490.                         paddleSpriteP->moveBoundsRect.left) / 2;
  491.     short    paddleWidth = (paddleSpriteP->destFrameRect.right - 
  492.                             paddleSpriteP->destFrameRect.left);
  493.     Point    globalPoint;
  494.     
  495.     
  496.     GetMouse(&newPoint);
  497.     globalPoint = newPoint;
  498.     LocalToGlobal(&globalPoint);
  499.     
  500.     if (globalPoint.h < middle)
  501.     {
  502.         SWSetSpriteLocation(paddleSpriteP, paddleSpriteP->moveBoundsRect.left +
  503.                                     globalPoint.h, paddleSpriteP->moveBoundsRect.bottom - 30);
  504.     }
  505.     else if (qd.screenBits.bounds.right - globalPoint.h < middle)
  506.     {
  507.         SWSetSpriteLocation(paddleSpriteP, paddleSpriteP->moveBoundsRect.right+1 -
  508.                                     (qd.screenBits.bounds.right - globalPoint.h) - paddleWidth, 
  509.                                     paddleSpriteP->moveBoundsRect.bottom - 30);
  510.     }
  511.     else
  512.     {
  513.         SWSetSpriteLocation(paddleSpriteP, paddleSpriteP->moveBoundsRect.left +
  514.                         middle - paddleWidth/2, paddleSpriteP->moveBoundsRect.bottom - 30);
  515.     }
  516. }
  517.  
  518.  
  519. ///--------------------------------------------------------------------------------------
  520. // PaddleMoveProc
  521. ///--------------------------------------------------------------------------------------
  522.  
  523. void PaddleMoveProc(SpritePtr paddleSpriteP)
  524. {
  525.     oldPoint = newPoint;
  526.     GetMouse(&newPoint);
  527.  
  528.     SWOffsetSprite(paddleSpriteP, newPoint.h - oldPoint.h, 0);
  529.     
  530.     if (paddleSpriteP->destFrameRect.left < paddleSpriteP->moveBoundsRect.left)
  531.     {
  532.         SWOffsetSprite(paddleSpriteP, (paddleSpriteP->moveBoundsRect.left - 
  533.                             paddleSpriteP->destFrameRect.left) , 0);
  534.     }
  535.     else if (paddleSpriteP->destFrameRect.right > paddleSpriteP->moveBoundsRect.right)
  536.     {
  537.         SWOffsetSprite(paddleSpriteP, (paddleSpriteP->moveBoundsRect.right - 
  538.                             paddleSpriteP->destFrameRect.right) , 0);
  539.     }
  540. }
  541.  
  542.  
  543. ///--------------------------------------------------------------------------------------
  544. // BallMoveProc
  545. ///--------------------------------------------------------------------------------------
  546.  
  547. void BallMoveProc(SpritePtr srcSpriteP)
  548. {
  549.     register short         inset;
  550.     
  551.     
  552.         // Move the sprite
  553.     SWOffsetSprite(srcSpriteP, srcSpriteP->horizMoveDelta, srcSpriteP->vertMoveDelta);
  554.     
  555.  
  556.         // Check for collision with walls
  557.     if ((srcSpriteP->destFrameRect.left < srcSpriteP->moveBoundsRect.left) &&
  558.             (srcSpriteP->horizMoveDelta < 0))        // Past left bounds and moving left
  559.     {
  560.         srcSpriteP->horizMoveDelta *= -1;            // Reverse direction
  561.         inset = srcSpriteP->moveBoundsRect.left - srcSpriteP->destFrameRect.left;
  562.         SWOffsetSprite( srcSpriteP, inset * 2, 0 );    // "Bounce" sprite off bounds
  563.  
  564.     }
  565.     else if ((srcSpriteP->destFrameRect.right > srcSpriteP->moveBoundsRect.right)&&
  566.                 (srcSpriteP->horizMoveDelta > 0))    // Past right bounds and moving right
  567.     {
  568.         srcSpriteP->horizMoveDelta *= -1;            // Reverse direction
  569.         inset = srcSpriteP->moveBoundsRect.right - srcSpriteP->destFrameRect.right;
  570.         SWOffsetSprite( srcSpriteP, inset * 2, 0 );    // "Bounce" sprite off bounds
  571.     }
  572.  
  573.     if ((srcSpriteP->destFrameRect.top < srcSpriteP->moveBoundsRect.top) &&
  574.             (srcSpriteP->vertMoveDelta < 0))        // Past top bounds and moving up
  575.     {
  576.         srcSpriteP->vertMoveDelta *= -1;            // Reverse direction
  577.         inset = srcSpriteP->moveBoundsRect.top - srcSpriteP->destFrameRect.top;
  578.         SWOffsetSprite( srcSpriteP, 0, inset * 2 );    // "Bounce" sprite off bounds
  579.     }
  580.     else if ((srcSpriteP->oldFrameRect.top > srcSpriteP->moveBoundsRect.bottom)&&
  581.                 (srcSpriteP->vertMoveDelta > 0))    // Past bottom bounds and moving down
  582.     {
  583.         SysBeep(1);
  584.         srcSpriteP->userData++;
  585.  
  586.         SWSetSpriteLocation(srcSpriteP, -100, 50);
  587.  
  588.         SWSetSpriteMoveDelta(srcSpriteP, kBallHorizDelta, kBallVertDelta);
  589.     }
  590. }
  591.